home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / netupdate.c < prev    next >
C/C++ Source or Header  |  1993-01-15  |  32KB  |  1,441 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. /*
  16.  * Incremental net changes are provides by the following commands:
  17.  * 
  18.  * alias node        '==' <node> <node_name>
  19.  * alias node_ref    '=' <node> <node_ref>
  20.  * create new node    'n' <node> <cap> <node_name>
  21.  * eliminate node    'e' <node>
  22.  * eliminate node    'E' <node_name>
  23.  * change node cap    'C' <node> <delta_cap>
  24.  * set node cap        'C' <node> '='<cap>
  25.  * rename node        'r' <node> <node_name>
  26.  * hierarchical rename    'h' <node> <node_name> [ <old_name> ]
  27.  * connect nodes    'c' <node> <node>
  28.  * break node        'b' <node> <new_node> <cap> <node_name>
  29.  * 
  30.  * add new transistor    'a' <type> <x> <y> <length> <width> <gate> <src> <drn>
  31.  * delete transistor    'd' <x> <y>
  32.  * exchange src/drn    'x' <x> <y>
  33.  * change trans. size    's' <x> <y> <length> <width>
  34.  * change position    'p' <x> <y> <new_x> <new_y>
  35.  * move trans. terminal    'm' <x> <y> <new_gate> <new_src> <new_drn>
  36.  * move trans. to node    'M' <x> <y> <new_node> ['g']['s']['d']
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include "defs.h"
  41. #include "net.h"
  42. #include "globals.h"
  43. #include "net_macros.h"
  44.  
  45.  
  46. extern    char    *ctime();
  47. extern    long    time();
  48.  
  49.  
  50. /******** ALIAS MANAGMENT ******/
  51.  
  52. #define    ALIAS_TBL_SIZE        512
  53. #define    LOG2_TBL_SIZE        9
  54. #define    AliasTblIndex( N )    ( (N) & (ALIAS_TBL_SIZE - 1) )
  55. #define    AliasTblBucket( N )    ( (N) >> LOG2_TBL_SIZE )
  56. #define    SIZEOF( A )        ( (int) sizeof( A ) )
  57.  
  58.  
  59. typedef struct
  60.   {
  61.     nptr    **bucket;
  62.     int     size;
  63.   } Aliases;
  64.  
  65.  
  66. private    Aliases    aliases;
  67.  
  68.  
  69. private void InitAliasTbl()
  70.   {
  71.     int  i;
  72.  
  73.     aliases.size = 20;            /* default initial size */
  74.  
  75.     aliases.bucket = (nptr **) Valloc( SIZEOF( nptr * ) * aliases.size, 1 );
  76.     for( i = 0; i < aliases.size; i++ )
  77.     aliases.bucket[ i ] = NULL;
  78.   }
  79.  
  80.  
  81. void FreeAliasTbl()
  82.   {
  83.     int  i;
  84.  
  85.     if( aliases.bucket != NULL )
  86.       {
  87.     for( i = 0; i < aliases.size; i++ )
  88.       {
  89.         if( aliases.bucket[ i ] != NULL )
  90.         Vfree( aliases.bucket[ i ] );
  91.       }
  92.     Vfree( aliases.bucket );
  93.       }
  94.     aliases.bucket = NULL;
  95.     aliases.size = 0;
  96.   }
  97.  
  98.  
  99. private void IncreaseAliasTbl( i )
  100.   int   i;
  101.   {
  102.     Aliases  old;
  103.  
  104.     old = aliases;
  105.  
  106.     do { aliases.size *= 2; } while( i >= aliases.size );
  107.  
  108.     aliases.bucket = (nptr **) Valloc( SIZEOF( nptr * ) * aliases.size, 1 );
  109.     for( i = 0; i < old.size; i++ ) aliases.bucket[ i ] = old.bucket[ i ];
  110.     while( i < aliases.size ) aliases.bucket[ i++ ] = NULL;
  111.     Vfree( old.bucket );
  112.   }
  113.  
  114.  
  115. private void EnterAlias( n, nd )
  116.   register int  n;
  117.   nptr          nd;
  118.   {
  119.     register int   i;
  120.     register nptr  *tbl;
  121.  
  122.     i = AliasTblBucket( n );
  123.     if( i >= aliases.size )
  124.     IncreaseAliasTbl( i );
  125.  
  126.     if( (tbl = aliases.bucket[ i ]) == NULL )
  127.       {
  128.     register nptr  *t, *t_end;
  129.  
  130.     tbl = (nptr *) Valloc( SIZEOF( nptr ) * ALIAS_TBL_SIZE, 1 );
  131.     aliases.bucket[ i ] = tbl;
  132.     for( t = tbl, t_end = t + ALIAS_TBL_SIZE; t < t_end; *t++ = NULL );
  133.       }
  134.  
  135.     tbl[ AliasTblIndex( n ) ] = nd;
  136.   }
  137.  
  138.  
  139. private nptr LookupAlias( n )
  140.   register int  n;
  141.   {
  142.     register int   i;
  143.     register nptr  *t, nd;
  144.  
  145.     i = AliasTblBucket( n );
  146.     if( i >= aliases.size or (t = aliases.bucket[ i ]) == NULL )
  147.     return( NULL );
  148.     nd = t[ AliasTblIndex( n ) ];
  149.     while( nd != NULL and (nd->nflags & ALIAS) )
  150.     nd = nd->nlink;
  151.     return( nd );
  152.   }
  153.  
  154. /***** END OF ALIAS MANAGMENT ******/
  155.  
  156.  
  157. #define LSIZE        2000        /* size for input line buffer */
  158. #define    MAXARGS        20        /* max. # of arguments per line */
  159.  
  160. #define    streq( A, B )    ( strcmp( (A), (B) ) == 0 )
  161.  
  162.  
  163.     /* a capacitance change > CAP_THRESH % will consider the node changed */
  164. #define    CAP_THRESH    (0.05)        /* default is now 5% */
  165.  
  166.  
  167. private    int    lineno;            /* current input file line number */
  168. private    char    *nu_fname;        /* current input filename */
  169. private    int    num_errors;        /* number of errors in input file */
  170. private    FILE    *nu_logf;        /* file for recording net changes */
  171. private    int    context;        /* 0 for old transistor context */
  172. private    int    num_deleted;        /* number of nodes deleted */
  173. private    int    num_cap_set;        /* number of nodes with cap set */
  174. private    nptr    ch_nlist;        /* list of nodes that were changed */
  175. private    tptr    ch_tran;        /* list of changed transistors */
  176. private    nptr    new_GND, new_VDD;
  177. private    int    chg_VDD, chg_GND;
  178. private    void    nu_error();
  179.  
  180.  
  181.     /* value stored in tflags, indicating how transistor changed */
  182. #define    T_CH_POS    0x1
  183. #define    T_CHK_TERM    0x2
  184. #define    T_MOV_GATE    0x4
  185. #define    T_MOV_SRC    0x8
  186. #define    T_MOV_DRN    0x10
  187. #define    T_ADDED        ( T_CH_POS | T_MOV_GATE | T_MOV_SRC | T_MOV_DRN )
  188.  
  189. #define    N_CAP_SET    (STIM)
  190.  
  191.  
  192. #define    TRAN_CHANGE( T, WHAT )            \
  193.   {                        \
  194.     if( (T)->tflags == 0 )            \
  195.       {                        \
  196.     (T)->dcache.t = ch_tran;        \
  197.     (T)->scache.t = ch_tran->scache.t;    \
  198.     ch_tran->scache.t->dcache.t = (T);    \
  199.     ch_tran->scache.t = (T);        \
  200.       }                        \
  201.     (T)->tflags |= (WHAT);            \
  202.   }
  203.  
  204.  
  205. #define    CAP_CHANGE( ND, LIST, GCAP )        \
  206.   {                        \
  207.     if( not ((ND)->nflags & VISITED) )        \
  208.       {                        \
  209.     (ND)->n.next = (LIST);            \
  210.     LIST = (ND);                \
  211.     (ND)->nflags |= VISITED;        \
  212.     (ND)->c.cap = (ND)->ncap;        \
  213.       }                        \
  214.     (ND)->ncap += (GCAP);            \
  215.   }                        \
  216.  
  217.  
  218. #define    NODE_CHANGE( ND, LIST )            \
  219.   {                        \
  220.     if( not ((ND)->nflags & VISITED) )        \
  221.       {                        \
  222.     (ND)->n.next = (LIST);            \
  223.     LIST = (ND);                \
  224.       }                        \
  225.     (ND)->nflags |= (VISITED | CHANGED);    \
  226.   }                        \
  227.  
  228.  
  229. #define Error( A )    \
  230.  if( 1 ) {        \
  231.     nu_error A ;    \
  232.     return;        \
  233.   } else        \
  234.  
  235.  
  236. private    char    bad_arg_msg[] = "Wrong # of arguments for '%s' expect %s\n";
  237. private    char    bad_alias_msg[] = "Illegal alias number (%d)\n";
  238. private    char    no_node_msg[] = "can not find node %s\n";
  239. private    char    no_alias_msg[] = "Non-existent node alias (%d)\n";
  240. private    char    no_trans_msg[] = "can not find transistor @ %d,%d\n";
  241.  
  242.  
  243. #define    FindNode( ND, ARG )     \
  244.   {                \
  245.     int  Nnum = atoi( ARG );    \
  246.     if( Nnum < 0 )        \
  247.     Error( (bad_alias_msg, Nnum) ); \
  248.     if( ((ND) = LookupAlias( Nnum )) == NULL ) \
  249.     Error( (no_alias_msg, Nnum) ); \
  250.   }
  251.  
  252.  
  253. #define    ff2pf( C )    ( (C) * 0.001 )        /* ff to pf */
  254.  
  255.  
  256. private void alias_node( ac, av )
  257.   int   ac;
  258.   char  *av[];
  259.   {
  260.     int   nnum;
  261.     nptr  nd;
  262.  
  263.     if( ac != 3 )    Error( (bad_arg_msg, av[0], "3") );
  264.  
  265.     nnum = atoi( av[1] );
  266.     if( nnum < 0 )    Error( (bad_alias_msg, nnum) );
  267.  
  268.     nd = (av[0][1] != '=') ? FindNode_TxtorPos( av[2] ) : GetNode( av[2] );
  269.     if( nd == NULL )
  270.     Error( (no_node_msg, av[2]) );
  271.  
  272.     EnterAlias( nnum, nd );
  273.   }
  274.  
  275.  
  276. private void new_node( ac, av )
  277.   int   ac;
  278.   char  *av[];
  279.   {
  280.     nptr    nd;
  281.     int     n;
  282.     double  cap;
  283.     
  284.     if( ac != 4 )    Error( (bad_arg_msg, av[0], "4") );
  285.  
  286.     cap = ff2pf( atoi( av[2] ) );
  287.     n = atoi( av[1] );
  288.     if( n < 0 )        Error( (bad_alias_msg, n) );
  289.  
  290.     nd = GetNewNode( av[3] );
  291.     nd->ncap = cap;
  292.     NODE_CHANGE( nd, ch_nlist );
  293.  
  294.     EnterAlias( n, nd );
  295.   }
  296.  
  297.  
  298. private void eliminate_node( ac, av )
  299.   int   ac;
  300.   char  *av[];
  301.   {
  302.     nptr  nd;
  303.  
  304.     if( ac != 2 )        Error( (bad_arg_msg, av[0], "2") );
  305.  
  306.     if( av[0][0] == 'E' )
  307.       {
  308.     nd = find( av[1] );
  309.     if( nd == NULL )    Error( (no_node_msg, av[1]) );
  310.     while( nd->nflags & ALIAS )
  311.         nd = nd->nlink;
  312.       }
  313.     else
  314.       {
  315.     FindNode( nd, av[1] );
  316.       }
  317.  
  318.     if( nd->nflags & POWER_RAIL )        /* never delete Vdd or Gnd */
  319.     return;
  320.     n_delete( nd );
  321.     NODE_CHANGE( nd, ch_nlist );
  322.     nd->nflags |= DELETED;
  323.     nnodes--;
  324.     num_deleted += 1;
  325.   }
  326.  
  327.  
  328. private void change_cap( ac, av )
  329.   int   ac;
  330.   char  *av[];
  331.   {
  332.     int     n;
  333.     nptr    nd;
  334.     double  cap;
  335.  
  336.     if( ac != 3 )    Error( (bad_arg_msg, av[0], "3") );
  337.  
  338.     FindNode( nd, av[1] );
  339.  
  340.     if( av[2][0] == '=' )
  341.       {
  342.     cap = ff2pf( atoi( &av[2][1] ) );
  343.     CAP_CHANGE( nd, ch_nlist, 0 );
  344.     nd->ncap = cap;
  345.     nd->nflags |= N_CAP_SET;
  346.     num_cap_set ++;
  347.       }
  348.     else
  349.       {
  350.     cap = ff2pf( atoi( av[2] ) );
  351.     CAP_CHANGE( nd, ch_nlist, cap );
  352.       }
  353.   }
  354.  
  355.  
  356. private void ChangeNodeName( nd, str )
  357.   nptr  nd;
  358.   char  *str;
  359.   {
  360.     int  len;
  361.  
  362.     if( nd->nflags & POWER_RAIL )
  363.       {
  364.     if( str_eql( str, nd->nname ) == 0 )
  365.         return;
  366.     else if( nd == GND_node )
  367.         chg_GND = TRUE;
  368.     else
  369.         chg_VDD = TRUE;
  370.       }
  371.  
  372.     len = strlen( str ) + 1;
  373.  
  374.     n_delete( nd );
  375.  
  376.     nd->nname = Valloc( len, 1 );
  377.     bcopy( str, nd->nname, len );
  378.  
  379.     CAP_CHANGE( nd, ch_nlist, 0 );
  380.  
  381.     if( str_eql( str, "Vdd" ) )
  382.     new_VDD = nd;
  383.     else if( str_eql( str, "Gnd" ) )
  384.     new_GND = nd;
  385.   }
  386.  
  387.  
  388. private void rename_node( ac, av )
  389.   int   ac;
  390.   char  *av[];
  391.   {
  392.     int   n;
  393.     nptr  nd;
  394.  
  395.     if( ac != 3 )    Error( (bad_arg_msg, av[0], "3") );
  396.  
  397.     FindNode( nd, av[1] );
  398.  
  399.     if( not streq( nd->nname, av[2] ) )
  400.     ChangeNodeName( nd, av[2] );
  401.   }
  402.  
  403.  
  404. /*
  405.  * Return TRUE if 'name1' is "better" than 'name2', FALSE otherwise.
  406.  */
  407. private int BestNodeName( name1, name2 )
  408.   char *name1, *name2;
  409.   {
  410.     register int nslashes1, nslashes2;
  411.     register char *np1, *np2;
  412.  
  413.     for( nslashes1 = 0, np1 = name1; *np1; )
  414.       {
  415.     if( *np1++ == '/' )  nslashes1++;
  416.      }
  417.  
  418.     for( nslashes2 = 0, np2 = name2; *np2; )
  419.       {
  420.     if( *np2++ == '/' )  nslashes2++;
  421.       }
  422.  
  423.     --np1;
  424.     --np2;
  425.  
  426.     /* chose label over generated name */
  427.     if( *np1 != '#' && *np2 == '#' )    return( TRUE );
  428.     if( *np1 == '#' && *np2 != '#' )    return( FALSE );
  429.  
  430.     /* either both are labels or generated names */
  431.     /* check pathname components */
  432.     if( nslashes1 < nslashes2 )        return( TRUE );
  433.     if( nslashes1 > nslashes2 )        return( FALSE );
  434.  
  435.     /* same # of pathname components; check length */
  436.     if( np1 - name1 < np2 - name2 )    return( TRUE );
  437.     if( np1 - name1 > np2 - name2 )    return( FALSE );
  438.  
  439.     /* same # of pathname components; same length; use lex ordering */
  440.     return( (strcmp( name1, name2 ) > 0) ? TRUE : FALSE );
  441.   }
  442.  
  443.  
  444.  
  445. private void hier_rename_node( ac, av )
  446.   int   ac;
  447.   char  *av[];
  448.   {
  449.     nptr  nd;
  450.  
  451.     if( ac < 3 or ac > 4 )
  452.     Error( (bad_arg_msg, av[0], "3-4") );
  453.  
  454.     FindNode( nd, av[1] );
  455.  
  456.     if( ac == 3 )
  457.       {
  458.     if( BestNodeName( av[2], nd->nname ) )
  459.         ChangeNodeName( nd, av[2] );
  460.       }
  461.     else if( streq( nd->nname, av[ 3 ] ) )
  462.     ChangeNodeName( nd, av[2] );
  463.   }
  464.  
  465.  
  466. private void connect_nodes( ac, av )
  467.   int   ac;
  468.   char  *av[];
  469.   {
  470.     int            t_terms;
  471.     register nptr  nd1, nd2;
  472.     register lptr  l;
  473.  
  474.     if( ac != 3 )    Error( (bad_arg_msg, av[0], "3") );
  475.  
  476.     FindNode( nd1, av[1] );
  477.     FindNode( nd2, av[2] );
  478.  
  479.     if( nd1 == nd2 )
  480.     return;
  481.  
  482.     if( (nd1->nflags & nd2->nflags) & POWER_RAIL )
  483.     Error( ("Warning: attempt to short Vdd & Gnd\n") );
  484.  
  485.     if( (nd2->nflags & POWER_RAIL) or BestNodeName( nd2->nname, nd1->nname ) )
  486.     SWAP_NODES( nd1, nd2 );
  487.  
  488.     if( nd2->ngate != NULL )
  489.       {
  490.     register lptr  last;
  491.  
  492.     for( l = nd2->ngate; l != NULL; l = l->next )
  493.       {
  494.         l->xtor->gate = nd1;
  495.         last = l;
  496.       }
  497.     last->next = nd1->ngate;
  498.     nd1->ngate = nd2->ngate;
  499.       }
  500.  
  501.     if( nd2->nterm != NULL )
  502.       {
  503.     register lptr  last;
  504.     register tptr  t;
  505.  
  506.     for( l = nd1->nterm; l != NULL; l = l->next )
  507.       {
  508.         t = l->xtor;
  509.         TRAN_CHANGE( t, T_CHK_TERM );
  510.       }
  511.     for( l = nd2->nterm; l != NULL; l = l->next )
  512.       {
  513.         t = l->xtor;
  514.         if( t->source == nd2 ) t->source = nd1;
  515.         if( t->drain == nd2 ) t->drain = nd1;
  516.         TRAN_CHANGE( t, T_CHK_TERM );
  517.         last = l;
  518.       }
  519.  
  520.     if( nd1->nflags & POWER_RAIL )
  521.         last->next = freeLinks,    freeLinks = nd2->nterm;
  522.     else
  523.         last->next = nd1->nterm,    nd1->nterm = nd2->nterm;
  524.  
  525.     t_terms = TRUE;
  526.       }
  527.     else
  528.     t_terms = FALSE;
  529.  
  530.     for( l = on_trans; l != NULL; l = l->next )
  531.       {
  532.     if( l->xtor->gate == nd2 ) l->xtor->gate = nd1;
  533.       }
  534.  
  535.     if( tcap->scache.t != tcap )
  536.       {
  537.     register tptr  t;
  538.  
  539.     for( t = tcap->scache.t; t != tcap; t = t->scache.t )
  540.       {
  541.         if( t->gate == nd2 )    t->gate = nd1;
  542.         if( t->source == nd2 )    t->source = nd1;
  543.         if( t->drain == nd2 )    t->drain = nd1;
  544.       }
  545.       }
  546.  
  547.     n_delete( nd2 );
  548.  
  549.     nd2->ngate = nd2->nterm = NULL;
  550.     nd2->nlink = nd1;
  551.     nd2->nflags = (ALIAS | DELETED);
  552.     num_deleted += 1;
  553.     nnodes--;
  554.  
  555.     NODE_CHANGE( nd2, ch_nlist );
  556.  
  557.     CAP_CHANGE( nd1, ch_nlist, nd2->ncap );
  558.     nd2->ncap = 0.0;
  559.     if( t_terms )
  560.     nd1->nflags |= CHANGED;
  561.   }
  562.  
  563.  
  564. private void break_node( ac, av )
  565.   int   ac;
  566.   char  *av[];
  567.   {
  568.     int     nnum;
  569.     double  cap;
  570.     nptr    nd, new_nd;
  571.  
  572.     if( ac != 5 )    Error( (bad_arg_msg, av[0], "5") );
  573.  
  574.     FindNode( nd, av[1] );
  575.     CAP_CHANGE( nd, ch_nlist, 0.0 );
  576.  
  577.     nnum = atoi( av[2] );
  578.     if( nnum < 0 )    Error( (bad_alias_msg, nnum) );
  579.  
  580.     cap = ff2pf( atoi( av[3] ) );
  581.     new_nd = GetNewNode( av[4] );
  582.     new_nd->ncap = cap;
  583.     EnterAlias( nnum, new_nd );
  584.     NODE_CHANGE( new_nd, ch_nlist );
  585.   }
  586.  
  587.  
  588. private void add_new_trans( ac, av )
  589.   int   ac;
  590.   char  *av[];
  591.   {
  592.     struct Trans  tran;
  593.     tptr          t;
  594.     long          length, width;
  595.     double        cap;
  596.  
  597.     if( ac != 9 )    Error( (bad_arg_msg, av[0], "9") );
  598.  
  599.     switch( av[1][0] )
  600.       {
  601.     case 'n' :    tran.ttype = NCHAN;    break;
  602.     case 'p' :    tran.ttype = PCHAN;    break;
  603.     case 'd' :    tran.ttype = DEP;    break;
  604.     default :
  605.         nu_error( "unknown transistor type (%s)\n", av[1] );
  606.         return;
  607.       }
  608.  
  609.     tran.x.pos = atoi( av[2] );
  610.     tran.y.pos = atoi( av[3] );
  611.     length = atof( av[4] ) * LAMBDACM;
  612.     width = atof( av[5] ) * LAMBDACM;
  613.  
  614.     FindNode( tran.gate, av[6] );
  615.     FindNode( tran.source, av[7] );
  616.     FindNode( tran.drain, av[8] );
  617.  
  618.     tran.tflags = tran.n_par = 0;
  619.     tran.state = (tran.ttype & ALWAYSON) ? WEAK : UNKNOWN;
  620.  
  621.     ntrans[ tran.ttype ]++;
  622.  
  623.     NEW_TRANS( t );
  624.     *t = tran;
  625.     t->r = requiv( (int) tran.ttype, width, length );
  626.  
  627.     t->tlink = t;
  628.  
  629.     cap = length * width * CTGA;
  630.     CAP_CHANGE( t->gate, ch_nlist, cap );
  631.  
  632.     if( (config_flags & TDIFFCAP) and (cap = CTDW * width + CTDE) != 0.0 )
  633.       {
  634.     CAP_CHANGE( t->source, ch_nlist, cap );
  635.     CAP_CHANGE( t->drain, ch_nlist, cap );
  636.       }
  637.     if( t->source != t->drain )
  638.       {
  639.     NODE_CHANGE( t->source, ch_nlist );
  640.     NODE_CHANGE( t->drain, ch_nlist );
  641.       }
  642.  
  643.     TRAN_CHANGE( t, T_ADDED );
  644.   }
  645.  
  646.  
  647. #define    FindTxtor( T, X_STR, Y_STR, X, Y )    \
  648.   {                        \
  649.     X = atoi( X_STR );                \
  650.     Y = atoi( Y_STR );                \
  651.     if( ((T) = FindTxtorPos( X, Y )) == NULL )    \
  652.       {                        \
  653.     nu_error( no_trans_msg, X, Y );     \
  654.     return;                    \
  655.       }                        \
  656.   }
  657.  
  658.  
  659. private void delete_trans( ac, av )
  660.   int   ac;
  661.   char  *av[];
  662.   {
  663.     tptr    t;
  664.     long    x, y;
  665.     double  cap, gcap;
  666.  
  667.     if( ac != 3 )    Error( (bad_arg_msg, av[0], "3") );
  668.  
  669.     FindTxtor( t, av[1], av[2], x, y );
  670.  
  671.     DeleteTxtorPos( t );
  672.  
  673.     gcap = -(t->r->width * t->r->length * CTGA);
  674.     cap = (config_flags & TDIFFCAP) ? -(CTDW * t->r->width + CTDE) : 0.0;
  675.  
  676.     if( t->ttype & TCAP )
  677.       {
  678.     if( cap != 0.0 )
  679.       {
  680.         CAP_CHANGE( t->source, ch_nlist, cap );
  681.         CAP_CHANGE( t->drain, ch_nlist, cap );
  682.       }
  683.     UNLINK_TCAP( t );
  684.       }
  685.     else
  686.       {
  687.     if( t->ttype & STACKED ) DestroyStack( t->dcache.t );
  688.     if( t->ttype & ORLIST ) UnParallelTrans( t );
  689.  
  690.     if( t->ttype & ALWAYSON )
  691.       {
  692.         DISCONNECT( on_trans, t );
  693.       }
  694.     else
  695.       {
  696.         DISCONNECT( t->gate->ngate, t );
  697.       }
  698.     DISCONNECT( t->source->nterm, t );
  699.     DISCONNECT( t->drain->nterm, t );
  700.  
  701.     NODE_CHANGE( t->source, ch_nlist );
  702.     NODE_CHANGE( t->drain, ch_nlist );
  703.     if( cap != 0.0 )
  704.       {
  705.         t->source->ncap += cap;
  706.         t->drain->ncap += cap;
  707.       }
  708.     if( t->tflags != 0 )    /* it is in changed list -> remove it */
  709.       {
  710.         t->dcache.t->scache.t = t->scache.t;
  711.         t->scache.t->dcache.t = t->dcache.t;
  712.       }
  713.       }
  714.     CAP_CHANGE( t->gate, ch_nlist, gcap );
  715.     ntrans[ BASETYPE( t->ttype ) ] -= 1;
  716.     FREE_TRANS( t );
  717.   }
  718.  
  719.  
  720. private void exchange_terms( ac, av )
  721.   int   ac;
  722.   char  *av[];
  723.   {
  724.     tptr  t;
  725.     long  x, y;
  726.  
  727.     if( ac != 3 )    Error( (bad_arg_msg, av[0], "3") );
  728.  
  729.     FindTxtor( t, av[1], av[2], x, y );
  730.  
  731.     SWAP_NODES( t->source, t->drain );
  732.   }
  733.  
  734.  
  735. private void change_tsize( ac, av )
  736.   int   ac;
  737.   char  *av[];
  738.   {
  739.     tptr     t;
  740.     long     x, y, length, width;
  741.     double   cap;
  742.     Resists  *old_r;
  743.  
  744.     if( ac != 5 )    Error( (bad_arg_msg, av[0], "5") );
  745.  
  746.     FindTxtor( t, av[1], av[2], x, y );
  747.  
  748.     length = atof( av[3] ) * LAMBDACM;
  749.     width = atof( av[4] ) * LAMBDACM;
  750.  
  751.     cap = (width * length - t->r->length * t->r->width) * CTGA;
  752.     CAP_CHANGE( t->gate, ch_nlist, cap );
  753.  
  754.     if( config_flags & TDIFFCAP )
  755.       {
  756.     cap = CTDW * (width - t->r->width) + CTDE;
  757.     CAP_CHANGE( t->source, ch_nlist, cap );
  758.     CAP_CHANGE( t->drain, ch_nlist, cap );
  759.       }
  760.  
  761.     old_r = t->r;
  762.     t->r = requiv( (int) t->ttype, width, length );
  763.  
  764.     if( old_r->dynlow != t->r->dynlow or old_r->dynhigh != t->r->dynhigh )
  765.       {
  766.     NODE_CHANGE( t->source, ch_nlist );
  767.     NODE_CHANGE( t->drain, ch_nlist );
  768.       }
  769.   }
  770.  
  771.  
  772. private void change_tposition( ac, av )
  773.   int   ac;
  774.   char  *av[];
  775.   {
  776.     tptr  t;
  777.     long  x, y;
  778.  
  779.     if( ac != 5 )    Error( (bad_arg_msg, av[0], "5") );
  780.  
  781.     FindTxtor( t, av[1], av[2], x, y );
  782.  
  783.     DeleteTxtorPos( t );
  784.  
  785.     t->x.pos = atoi( av[1] );
  786.     t->y.pos = atoi( av[2] );
  787.  
  788.     TRAN_CHANGE( t, T_CH_POS );
  789.   }
  790.  
  791.  
  792. private void move_trans_terms( ac, av )
  793.   int   ac;
  794.   char  *av[];
  795.   {
  796.     long    x, y, was_tcap = FALSE;
  797.     tptr    t;
  798.     nptr    gate, src, drn;
  799.     double  cap;
  800.  
  801. #    define IsDot( STR )    ((STR)[0] == '.' and (STR)[1] == '\0' )
  802.  
  803.     if( ac != 6 )    Error( (bad_arg_msg, av[0], "6") );
  804.  
  805.     FindTxtor( t, av[1], av[2], x, y );
  806.     
  807.     if( IsDot( av[3] ) )    gate = t->gate;    else FindNode( gate, av[3] );
  808.     if( IsDot( av[4] ) )    src = t->source;    else FindNode( src, av[4] );
  809.     if( IsDot( av[5] ) )    drn = t->drain;    else FindNode( drn, av[5] );
  810.  
  811.     if( gate == t->gate and src == t->source and drn == t->drain )
  812.     return;
  813.  
  814.     if( t->ttype & STACKED )    DestroyStack( t->dcache.t );
  815.     if( t->ttype & ORLIST )    UnParallelTrans( t );
  816.     if( t->ttype & TCAP )
  817.       {
  818.     UNLINK_TCAP( t );
  819.     was_tcap = TRUE;
  820.       }
  821.  
  822.     if( gate != t->gate )
  823.       {
  824.     if( gate->nflags & MERGED )
  825.       {
  826.         DestroyStack( gate->t.tran );
  827.         NODE_CHANGE( gate, ch_nlist );
  828.       }
  829.     cap = (t->r->width * t->r->length) * CTGA;
  830.     CAP_CHANGE( gate, ch_nlist, cap );
  831.     CAP_CHANGE( t->gate, ch_nlist, -cap );
  832.  
  833.     if( not (t->ttype & ALWAYSON) )
  834.       {
  835.         DISCONNECT( t->gate->ngate, t );
  836.         TRAN_CHANGE( t, T_MOV_GATE );
  837.       }
  838.     t->gate = gate;
  839.       }
  840.  
  841.     cap = (config_flags & TDIFFCAP) ? t->r->width * CTDW + CTDE : 0.0;
  842.  
  843.     if( t->source != src )
  844.       {
  845.     if( was_tcap )
  846.       {
  847.         CAP_CHANGE( t->source, ch_nlist, -cap );
  848.       }
  849.     else
  850.       {
  851.         DISCONNECT( t->source->nterm, t );
  852.         NODE_CHANGE( t->source, ch_nlist );
  853.         t->source->ncap -= cap;
  854.       }
  855.     src->ncap += cap;
  856.     t->source = src;
  857.     TRAN_CHANGE( t, T_MOV_SRC );
  858.       }
  859.  
  860.     if( t->drain != drn )
  861.       {
  862.     if( was_tcap )
  863.       {
  864.         CAP_CHANGE( t->drain, ch_nlist, -cap );
  865.       }
  866.     else
  867.       {
  868.         DISCONNECT( t->drain->nterm, t );
  869.         NODE_CHANGE( t->drain, ch_nlist );
  870.         t->drain->ncap -= cap;
  871.       }
  872.     drn->ncap += cap;
  873.     t->drain = drn;
  874.     TRAN_CHANGE( t, T_MOV_DRN );
  875.       }
  876.  
  877.     NODE_CHANGE( src, ch_nlist );
  878.     NODE_CHANGE( drn, ch_nlist );
  879.   }
  880.  
  881.  
  882. private void SwitchContext()
  883.   {
  884.     register tptr  t;
  885.  
  886.     if( context )
  887.     return;
  888.  
  889.     context = 1;
  890.  
  891.     for( t = ch_tran->scache.t; t != ch_tran; t = t->scache.t )
  892.       {
  893.     if( t->tflags & T_CH_POS )
  894.       {
  895.         EnterPos( t, TRUE );
  896.         t->tflags &= ~T_CH_POS;
  897.       }
  898.       }
  899.   }
  900.  
  901.  
  902. private void move_trans_to_node( ac, av )
  903.   int   ac;
  904.   char  *av[];
  905.   {
  906.     long    x, y, was_tcap = FALSE;
  907.     tptr    t;
  908.     nptr    nd, gate, src, drn;
  909.     char    *s;
  910.     double  cap;
  911.  
  912.     SwitchContext();
  913.  
  914.     if( ac != 5 )    Error( (bad_arg_msg, av[0], "5") );
  915.  
  916.     FindTxtor( t, av[1], av[2], x, y );
  917.  
  918.     FindNode( nd, av[3] );
  919.     
  920.     gate = t->gate;
  921.     src = t->source;
  922.     drn = t->drain;
  923.     for( s = av[4]; *s != '\0'; s++ )
  924.       {
  925.     if( *s == 'g' )        gate = nd;
  926.     else if( *s == 's' )    src = nd;
  927.     else if( *s == 'd' )    drn = nd;
  928.     else Error( ("Unknown terminal '%c'\n", *s) );
  929.       }
  930.  
  931.     if( gate == t->gate and src == t->source and drn == t->drain )
  932.     return;
  933.  
  934.     if( t->ttype & STACKED )    DestroyStack( t->dcache.t );
  935.     if( t->ttype & ORLIST )    UnParallelTrans( t );
  936.     if( t->ttype & TCAP )
  937.       {
  938.     UNLINK_TCAP( t );
  939.     was_tcap = TRUE;
  940.       }
  941.  
  942.     if( gate != t->gate )
  943.       {
  944.     if( t->ttype & ALWAYSON  )
  945.       {
  946.         DISCONNECT( on_trans, t );
  947.       }
  948.     else
  949.       {
  950.         DISCONNECT( t->gate->ngate, t );
  951.       }
  952.     t->gate = gate;
  953.     TRAN_CHANGE( t, T_MOV_GATE );
  954.     cap = (t->r->width * t->r->length) * CTGA;
  955.     gate->ncap += cap;
  956.       }
  957.  
  958.     cap = (config_flags & TDIFFCAP) ? t->r->width * CTDW + CTDE : 0.0;
  959.  
  960.     if( t->source != src )
  961.       {
  962.     if( not was_tcap )
  963.       {
  964.         DISCONNECT( t->source->nterm, t );
  965.       }
  966.     t->source = src;
  967.     src->ncap += cap;
  968.     TRAN_CHANGE( t, T_MOV_SRC );
  969.       }
  970.  
  971.     if( t->drain != drn )
  972.       {
  973.     if( not was_tcap )
  974.       {
  975.         DISCONNECT( t->drain->nterm, t );
  976.       }
  977.     t->drain = drn;
  978.     drn->ncap += cap;
  979.     TRAN_CHANGE( t, T_MOV_DRN );
  980.       }
  981.   }
  982.  
  983.  
  984. private void change_thresh( ac, av )
  985.   int   ac;
  986.   char  *av[];
  987.   {
  988.     nptr   nd;
  989.     float  vlow, vhigh;
  990.  
  991.     if( ac != 4 )    Error( (bad_arg_msg, av[0], "4") );
  992.     nd = find( av[1] );
  993.     while( nd->nflags & ALIAS ) nd = nd->nlink;
  994.     if( nd == NULL )    Error( (no_node_msg, av[1]) );
  995.     vlow = atof( av[2] );
  996.     vhigh = atof( av[3] );
  997.     if( nd->vlow != vlow or nd->vhigh != vhigh )
  998.       {
  999.     nd->vlow = vlow; nd->vhigh = vhigh;
  1000.     NODE_CHANGE( nd, ch_nlist );
  1001.       }
  1002.   }
  1003.  
  1004.  
  1005. private void ndelay( ac, av )
  1006.   int   ac;
  1007.   char  *av[];
  1008.   {
  1009.     nptr   nd;
  1010.     long   tplh, tphl;
  1011.  
  1012.     if( ac != 4 )    Error( (bad_arg_msg, av[0], "4") );
  1013.     nd = find( av[1] );
  1014.     while( nd->nflags & ALIAS ) nd = nd->nlink;
  1015.     if( nd == NULL )    Error( (no_node_msg, av[1]) );
  1016.     tplh = ns2d( atof( av[2] ) );
  1017.     tphl = ns2d( atof( av[3] ) );
  1018.  
  1019.     if( not (nd->nflags & USERDELAY) or nd->tplh != tplh or nd->tphl != tphl )
  1020.       {
  1021.     nd->tplh = tplh; nd->tphl = tphl;
  1022.     NODE_CHANGE( nd, ch_nlist );
  1023.       }
  1024.   }
  1025.  
  1026.  
  1027. /*
  1028.  * parse input line into tokens, filling up carg and setting targc
  1029.  */
  1030. private int parse_line( line, carg )
  1031.   register char  *line;
  1032.   register char  **carg;
  1033.   {
  1034.     register char  ch;
  1035.     register int   targc;
  1036.  
  1037.     targc = 0;
  1038.     while( ch = *line++ )
  1039.       {
  1040.     if( ch <= ' ' )
  1041.         continue;
  1042.     targc++;
  1043.     *carg++ = line - 1;
  1044.     while( *line > ' ' )
  1045.         line++;
  1046.     if( *line )
  1047.         *line++ = '\0';
  1048.       }
  1049.     *carg = 0;
  1050.     return( targc );
  1051.   }
  1052.  
  1053.  
  1054. private void input_changes( fin )
  1055.   FILE  *fin;
  1056.   {
  1057.     char  line[ LSIZE ];
  1058.     char  *targv[ MAXARGS ];
  1059.     int   targc;
  1060.  
  1061.     VDD_node->nflags |= VISITED;    /* never add these to 'change' list */
  1062.     GND_node->nflags |= VISITED;
  1063.     new_GND = new_VDD = NULL;
  1064.     chg_GND = chg_VDD = 0;
  1065.  
  1066.     InitAliasTbl();
  1067.  
  1068.     while( fgetline( line, LSIZE, fin ) != NULL )
  1069.       {
  1070.     lineno++;
  1071.     if( nu_logf )
  1072.         (void) fputs( line, nu_logf );
  1073.     targc = parse_line( line, targv );
  1074.     if( targc == 0 )
  1075.         continue;
  1076.  
  1077.     switch( targv[0][0] )
  1078.       {
  1079.         case '=' :    alias_node( targc, targv );        break;
  1080.         case 'n' :    new_node( targc, targv );        break;
  1081.         case 'e' :    eliminate_node( targc, targv );        break;
  1082.         case 'E' :    eliminate_node( targc, targv );        break;
  1083.         case 'C' :    change_cap( targc, targv );        break;
  1084.         case 'r' :    rename_node( targc, targv );        break;
  1085.         case 'h' :    hier_rename_node( targc, targv );    break;
  1086.         case 'c' :    connect_nodes( targc, targv );        break;
  1087.         case 'b' :    break_node( targc, targv );        break;
  1088.         case 'a' :    add_new_trans( targc, targv );        break;
  1089.         case 'd' :    delete_trans( targc, targv );        break;
  1090.         case 'x' :    exchange_terms( targc, targv );        break;
  1091.         case 's' :    change_tsize( targc, targv );        break;
  1092.         case 'p' :    change_tposition( targc, targv );    break;
  1093.         case 'm' :    move_trans_terms( targc, targv );    break;
  1094.         case 'M' :    move_trans_to_node( targc, targv );    break;
  1095.         case 't' :    change_thresh( targc, targv );        break;
  1096.         case 'D' :    ndelay( targc, targv );            break;
  1097.         case '|' :                        break;
  1098.         default :
  1099.         nu_error( "Unrecognized command (%s)\n", targv[0] );
  1100.       }
  1101.       }
  1102.  
  1103.     (void) fclose( fin );
  1104.     if( nu_logf )
  1105.     (void) fclose( nu_logf );
  1106.  
  1107.     FreeAliasTbl();
  1108.  
  1109.     VDD_node->nflags &= ~(VISITED | CHANGED);    /* restore flag */
  1110.     GND_node->nflags &= ~(VISITED | CHANGED);
  1111.   }
  1112.  
  1113.  
  1114. /*
  1115.  * Mark any alias that points to a deleted node as deleted.
  1116.  */
  1117. private int mark_del_alias( n )
  1118.   register nptr  n;
  1119.   {
  1120.     register nptr  nd;
  1121.     register int   has_del = FALSE;
  1122.  
  1123.     if( n->nflags & DELETED )
  1124.     return( 0 );
  1125.  
  1126.     for( nd = n; nd->nflags & ALIAS; nd = nd->nlink )
  1127.     if( nd->nflags & DELETED )
  1128.         has_del = TRUE;
  1129.  
  1130.     if( has_del )        /* deleted node(s) in alias list, resolve */
  1131.     n->nlink = nd;
  1132.  
  1133.     if( nd->nflags & DELETED )    /* points to a deleted node, delete as well */
  1134.       {
  1135.     n->nflags |= DELETED;
  1136.     n->nflags &= ~ALIAS;
  1137.     NODE_CHANGE( n, ch_nlist );
  1138.     naliases--;
  1139.       }
  1140.     return( 0 );
  1141.   }
  1142.  
  1143.  
  1144. private nptr rm_nodes()
  1145.   {
  1146.     register nptr  *nlast, node;
  1147.     nptr           nlist;
  1148.  
  1149.     if( num_deleted == 0 )
  1150.     return( ch_nlist );
  1151.  
  1152.     if( naliases > 0 )
  1153.     walk_net( mark_del_alias, (char *) 0 );
  1154.  
  1155.     rm_del_from_lists();
  1156.  
  1157.     nlist = NULL;
  1158.     nlast = &nlist;
  1159.  
  1160.     for( node = ch_nlist; node != NULL; node = node->n.next )
  1161.       {
  1162.     if( not (node->nflags & DELETED) )
  1163.       {
  1164.         *nlast = node;
  1165.         nlast = &node->n.next;
  1166.         continue;
  1167.       }
  1168.  
  1169.     while( node->events )        /* remove all pending events */
  1170.         free_event( node->events );
  1171.  
  1172.     if( IsInList( node->nflags ) )
  1173.         idelete( node, listTbl[INPUT_NUM( node->nflags )] );
  1174.  
  1175.     FreeHistList( node );
  1176.  
  1177.     if( node->hnext != node )
  1178.         n_delete( node );
  1179.  
  1180.     node->nlink = freeNodes;    /* return it to free pool */
  1181.     freeNodes = node;
  1182.       }
  1183.     *nlast = NULL;
  1184.  
  1185.     return( nlist );
  1186.   }
  1187.  
  1188.  
  1189. private void conn_ch_trans( tlist )
  1190.   tptr  tlist;
  1191.   {
  1192.     register lptr  l;
  1193.     register tptr  t;
  1194.     tptr           tnext;
  1195.     double         cap;
  1196.  
  1197.     for( t = tlist->scache.t; t != tlist; t = tnext )
  1198.       {
  1199.     tnext = t->scache.t;
  1200.  
  1201.     if( t->tflags & T_CH_POS )
  1202.         EnterPos( t, TRUE );
  1203.  
  1204.     if( t->tflags & (T_MOV_GATE | T_MOV_SRC | T_MOV_DRN) )
  1205.       {
  1206.         nptr  src = t->source, drn = t->drain;
  1207.  
  1208.         if( src == drn or (src->nflags & drn->nflags & POWER_RAIL) )
  1209.           {
  1210.         if( not (t->tflags & T_MOV_SRC) )
  1211.             DISCONNECT( src->nterm, t );
  1212.         if( not (t->tflags & T_MOV_DRN) )
  1213.             DISCONNECT( drn->nterm, t );
  1214.         if( t->ttype & ALWAYSON )
  1215.             DISCONNECT( on_trans, t )
  1216.         else if( t->tflags & T_MOV_GATE )
  1217.             DISCONNECT( t->gate->ngate, t );
  1218.  
  1219.         t->ttype |= TCAP;
  1220.         LINK_TCAP( t );
  1221.           }
  1222.         else
  1223.           {
  1224.         if( t->tflags & T_MOV_GATE )
  1225.           {
  1226.             if( t->ttype & ALWAYSON )
  1227.             CONNECT( on_trans, t )
  1228.             else
  1229.             CONNECT( t->gate->ngate, t );
  1230.           }
  1231.         if( (t->tflags & T_MOV_SRC) and not (src->nflags & POWER_RAIL) )
  1232.             CONNECT( src->nterm, t );
  1233.         if( (t->tflags & T_MOV_DRN) and not (drn->nflags & POWER_RAIL) )
  1234.             CONNECT( drn->nterm, t );
  1235.           }
  1236.       }
  1237.     else if( t->tflags & T_CHK_TERM )
  1238.       {
  1239.         nptr  src = t->source, drn = t->drain;
  1240.  
  1241.         if( src == drn or (src->nflags & drn->nflags & POWER_RAIL) )
  1242.           {
  1243.         DISCONNECT( src->nterm, t );
  1244.         DISCONNECT( drn->nterm, t );
  1245.         if( t->ttype & ALWAYSON )
  1246.             DISCONNECT( on_trans, t )
  1247.         else
  1248.             DISCONNECT( t->gate->ngate, t );
  1249.  
  1250.         t->ttype |= TCAP;
  1251.         LINK_TCAP( t );
  1252.           }
  1253.       }
  1254.     t->tflags = 0;
  1255.       }
  1256.   }
  1257.  
  1258.  
  1259. private void chk_power()
  1260.   {
  1261.     if( new_GND == NULL and chg_GND == 0 )
  1262.     ;
  1263.     else
  1264.       {
  1265.     fprintf( stderr, "Error: changed Gnd, cannot deal with this yet!\n" );
  1266.     exit( 1 );
  1267.       }
  1268.  
  1269.     if( new_VDD == NULL and chg_VDD == 0 )
  1270.     ;
  1271.     else
  1272.       {
  1273.     fprintf( stderr, "Error: changed Vdd, cannot deal with this yet!\n" );
  1274.     exit( 1 );
  1275.       }
  1276.   }
  1277.  
  1278.  
  1279. private void add_tran_cap( t )
  1280.   register tptr  t;
  1281.   {
  1282.     if( t->gate->nflags & N_CAP_SET )
  1283.     t->gate->ncap += t->r->width * t->r->length * CTGA;
  1284.     
  1285.     if( config_flags & TDIFFCAP )
  1286.       {
  1287.     if( t->source->nflags & N_CAP_SET )
  1288.         t->source->ncap += t->r->width * CTDW + CTDE;
  1289.     if( t->drain->nflags & N_CAP_SET )
  1290.         t->drain->ncap += t->r->width * CTDW + CTDE;
  1291.       }
  1292.   }
  1293.  
  1294.  
  1295. #define CHK_CAP( ND )    if( (ND)->ncap < MIN_CAP ) (ND)->ncap = MIN_CAP
  1296. #define    ABS( X )    ( ((X) < 0) ? -(X) : (X) )
  1297.  
  1298.  
  1299. private iptr changed_nodes()
  1300.   {
  1301.     register nptr  n;
  1302.     iptr           ilist = NULL;
  1303.  
  1304.     for( n = ch_nlist; n != NULL; n = n->n.next )
  1305.       {
  1306.     CHK_CAP( n );
  1307.  
  1308.     if( n->hnext == n )
  1309.         n_insert( n );
  1310.  
  1311.     n->nflags &= ~N_CAP_SET;
  1312.  
  1313.     if( not (n->nflags & CHANGED) )
  1314.       {
  1315.         double deltac = ABS( n->c.cap - n->ncap );
  1316.         if( deltac < CAP_THRESH * n->c.cap )
  1317.           {
  1318.         n->c.time = n->curr->time;
  1319.         continue;
  1320.           }
  1321.         n->nflags |= CHANGED;
  1322.       }
  1323.  
  1324.     if( n->nflags & MERGED )
  1325.       {
  1326.         register nptr  stack;
  1327.  
  1328.         stack = n->t.tran->source;
  1329.         if( not (stack->nflags & (CHANGED | POWER_RAIL)) )
  1330.           {
  1331.         iinsert( stack, &ilist );
  1332.         stack->nflags |= CHANGED;
  1333.           }
  1334.         stack = n->t.tran->drain;
  1335.         if( not (stack->nflags & (CHANGED | POWER_RAIL)) )
  1336.           {
  1337.         iinsert( stack, &ilist );
  1338.         stack->nflags |= CHANGED;
  1339.           }
  1340.         n->nflags &= ~CHANGED;
  1341.         continue;
  1342.       }
  1343.  
  1344.     if( n->nflags & POWER_RAIL )
  1345.         continue;
  1346.  
  1347.     iinsert( n, &ilist );
  1348.       }
  1349.     return( ilist );
  1350.   }
  1351.  
  1352.  
  1353. public iptr rd_changes( fname, logname )
  1354.   char  *fname;
  1355.   char  *logname;
  1356.   {
  1357.     FILE          *fin;
  1358.     iptr          ilist = NULL;
  1359.     struct Trans  dummyt;
  1360.     extern char   *getenv();
  1361.  
  1362.     ch_tran = dummyt.scache.t = dummyt.dcache.t = &dummyt;
  1363.     ch_nlist = NULL;
  1364.     context = num_cap_set = num_deleted = num_errors = lineno = 0;
  1365.     nu_fname = fname;
  1366.  
  1367.     if( (fin = fopen( fname, "r" )) == NULL )
  1368.       {
  1369.     lprintf( stderr, "can not open '%s' for net changes\n", fname );
  1370.     return( NULL );
  1371.       }
  1372.  
  1373.     if( logname == NULL )
  1374.     nu_logf = NULL;
  1375.     else if( (nu_logf = fopen( logname, "a" )) == NULL )
  1376.     lprintf( stderr, "warning: can't open logfile %s\n", logname );
  1377.     else
  1378.       {
  1379.     long  ltime = time( 0L );
  1380.     (void) fprintf( nu_logf, "| changes @ %s", ctime( <ime ) );
  1381.       }
  1382.  
  1383.     if( analyzerON )    StopAnalyzer();
  1384.  
  1385.     input_changes( fin );
  1386.  
  1387.     chk_power();
  1388.     ch_nlist = rm_nodes();
  1389.     conn_ch_trans( ch_tran );
  1390.     if( num_cap_set ) walk_trans( add_tran_cap, (char *) 0 );
  1391.     make_parallel( ch_nlist );
  1392.     make_stacks( ch_nlist );
  1393.  
  1394.     pTotalNodes();
  1395.     pTotalTxtors();
  1396.     pParallelTxtors();
  1397.     pStackedTxtors();
  1398.  
  1399.     ilist = changed_nodes();
  1400.  
  1401.     if( analyzerON )    RestartAnalyzer( sim_time0, sim_time0, FALSE );
  1402.  
  1403.     if( num_errors != 0 )
  1404.     lprintf( stderr, "%s contains %d errors\n", fname, num_errors,
  1405.       (nu_logf != NULL or logfile != NULL) ? " listed in logfile" : "" );
  1406.  
  1407.     if( getenv( "RSIM_CHANGED" ) != NULL )
  1408.       {
  1409.     iptr  ip;
  1410.  
  1411.     if( ilist != NULL ) lprintf( stdout, "changed nodes:\n" );
  1412.     for( ip = ilist; ip != NULL; ip = ip->next )
  1413.         lprintf( stdout, "  %s\n", pnode( ip->inode ) );
  1414.       }
  1415.  
  1416.     return( ilist );
  1417.   }
  1418.  
  1419.  
  1420. #include <varargs.h>
  1421.  
  1422. /* VARARGS */
  1423. private void nu_error( va_alist )
  1424.   va_dcl
  1425.   {
  1426.     va_list  args;
  1427.     char     *fmt, *errstr = "| error";
  1428.     FILE     *fp;
  1429.  
  1430.     if( nu_logf != NULL )    fp = nu_logf;
  1431.     else if( logfile != NULL )    fp = logfile;
  1432.     else            fp = stderr, errstr ++;
  1433.  
  1434.     va_start( args );
  1435.     fmt = va_arg( args, char * );
  1436.     (void) fprintf( fp, "%s:%s, line %d: ", errstr, nu_fname, lineno );
  1437.     (void) vfprintf( fp, fmt, args );
  1438.     va_end( args );
  1439.     num_errors += 1;
  1440.   }
  1441.